/**
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

package pittypat;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;

import pittypat.configuration.ConfigException;

/**
 * 提供一个功能的参数列表、功能路径、当前用户信息、是否执行成功的状态指示以及错误消息等信息。
 */
public final class FunctionModel<T extends FunctionArgs> extends Model {
	private String _path;
	private Boolean _success;
	private String _message;
	private T _args;
	private IUser _user;
	private DynamicModel _context;
	private DynamicModel _outArgs;

	/**
	 * 使用目标参数类型初始化 FuncModel 类的一个新实例。
	 * 
	 * @param argsType
	 *            实现了 FunctionArgs 的类型。
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	@SuppressWarnings("unchecked")
	public FunctionModel(Class<?> argsType) throws InstantiationException, IllegalAccessException {
		super();

		this._path = "";
		this._success = false;
		this._message = "";
		this._args = (T) argsType.newInstance();
		this._user = User.ANONYMOUS;
		this._context = null;
		this._outArgs = null;
	}

	/**
	 * 获取功能的参数列表。
	 */
	public T getArgs() {
		return this._args;
	}

	/**
	 * 获取所有输出参数的集合，包括方向为 Out 和 InOut 的两类参数。
	 * 
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws ConfigException
	 */
	public DynamicModel getOutArgs()
			throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, ConfigException {
		if (this._outArgs == null) {
			this._outArgs = new DynamicModel();
		}

		for (ParameterMeta f : FunctionMeta.find(this._args.getClass()).getParameters()) {
			this._outArgs.set(f.getCamelIdentifier(), this._args.getParameterValue(f.getCamelIdentifier()));
		}

		return this._outArgs;
	}

	/**
	 * 获取目标功能的路径，格式为 "开发者代码.App标识符.模块标识符.功能标识符"。
	 */
	public String getPath() {
		return this._path;
	}

	/**
	 * 甚至目标功能的路径，格式为 "开发者代码.App标识符.模块标识符.功能标识符"。
	 */
	public void setPath(String value) {
		this._path = value == null ? "" : value;
	}

	/**
	 * 获取一个值，该值指示功能是否执行成功。
	 */
	public boolean isSuccess() {
		return this._success;
	}

	/**
	 * 设置一个值，该值指示功能是否执行成功。
	 */
	public void setSuccess(Boolean value) {
		this._success = value;
	}

	/**
	 * 获取执行后产生的消息。
	 */
	public String getMessage() {
		return this._message;
	}

	/**
	 * 设置执行后产生的消息。
	 */
	public void setMessage(String value) {
		this._message = value == null ? "" : value;
	}

	/**
	 * 获取当前用户的信息，如果用户尚未登录，则返回一个匿名用户的信息。
	 */
	public IUser getUser() {
		return this._user;
	}

	/**
	 * 设置当前用户的信息，如果用户尚未登录，则返回一个匿名用户的信息。
	 * 
	 * @param value
	 *            目标用户对象，如果为 null，则设置为一个匿名用户。
	 */
	public void setUser(IUser value) {
		this._user = value == null ? User.ANONYMOUS : value;
	}

	/**
	 * 获取当前功能的环境变量。
	 * <p>
	 * 环境变量将被转换为 JSON 字符串传递给目标数据服务，存储过程等可以接收到这些变量参数，并根据参数值执行不同的业务数据操作。
	 * <p>
	 * 目前环境变量提供两个额外的参数：{lang: string, ip: string}，分别表示客户端使用的首选语言和客户端的 IP 地址。
	 * 
	 * @return 当前功能的环境变量。
	 */
	public DynamicModel getContext() {
		return this._context;
	}

	/**
	 * 设置当前功能的环境变量。
	 * 
	 * @param context
	 *            当前功能的环境变量。
	 */
	public void setContext(DynamicModel context) {
		this._context = context;
	}

	/**
	 * 将当前对象作为 JSON 字符串写入指定的文本流。DataModel 类编写为空对象：{}。
	 * 
	 * @param writer
	 *            目标文本流。
	 * @throws IllegalArgumentException
	 *             writer 是 null。
	 * @throws IOException
	 * @see pittypat.Model#write(java.io.Writer)
	 */
	@Override
	public void write(Writer writer) throws IOException {
		writer.write('{');

		writer.write("\"path\":");
		Json.write(writer, this._path);
		writer.write(',');

		writer.write("\"success\":");
		Json.write(writer, this._success);
		writer.write(',');

		writer.write("\"message\":");
		Json.write(writer, this._message);
		writer.write(',');

		writer.write("\"context\":");
		Json.write(writer, this._context);
		writer.write(',');

		writer.write("\"args\":");
		this._args.write(writer);

		writer.write('}');
	}
}
